package com.xz.sales.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.xz.apply.service.IPurchaseApplyService;
import com.xz.common.core.domain.AjaxResult;
import com.xz.common.core.domain.entity.SysDept;
import com.xz.common.exception.ServiceException;
import com.xz.common.utils.DateUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xz.common.utils.RedisCode;
import com.xz.common.utils.SecurityUtils;
import com.xz.common.utils.StringUtils;
import com.xz.diagnosis.vo.SalesPurchaseApplyVo;
import com.xz.expense.domain.ExpenseBill;
import com.xz.expense.mapper.ExpenseBillMapper;
import com.xz.member.domain.MemberInfo;
import com.xz.member.mapper.MemberInfoMapper;
import com.xz.member.service.IWalletRecordService;
import com.xz.message.service.ISysTenantNotifyItemService;
import com.xz.message.vo.MemberMsgInfo;
import com.xz.patient.domain.PatientInfo;
import com.xz.patient.mapper.PatientInfoMapper;
import com.xz.product.domain.Product;
import com.xz.product.mapper.ProductMapper;
import com.xz.purchase.domain.Purchase;
import com.xz.purchase.domain.PurchaseProduct;
import com.xz.purchase.mapper.PurchaseProductMapper;
import com.xz.purchase.service.IPurchaseService;
import com.xz.repertory.domain.RepertoryFlow;
import com.xz.repertory.service.IRepertoryFlowService;
import com.xz.sales.domain.*;
import com.xz.sales.mapper.*;
import com.xz.sales.param.SalesExchangeDetailParam;
import com.xz.sales.param.SalesExchangeParam;
import com.xz.sales.param.SalesReturnDetailParam;
import com.xz.sales.param.SalesReturnParam;
import com.xz.sales.service.ISalesOrderService;
import com.xz.sales.util.ProcessOrderUtil;
import com.xz.sales.vo.SalesExchangeVo;
import com.xz.system.mapper.SysDeptMapper;
import com.xz.system.service.ISysDeptService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.xz.sales.service.ISalesExchangeService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;

/**
 * 销售单换货Service业务层处理
 *
 * @author xz
 * @date 2024-02-05
 */
@Service
public class SalesExchangeServiceImpl  extends ServiceImpl<SalesExchangeMapper, SalesExchange> implements ISalesExchangeService
{
    @Autowired
    private SalesExchangeMapper salesExchangeMapper;
    @Resource
    private SalesOrderMapper salesOrderMapper;
    @Resource
    private SalesOrderDetailMapper orderDetailMapper;
    @Resource
    private SalesExchangeDetailMapper exchangeDetailMapper;
    @Resource
    private ExpenseBillMapper expenseBillMapper;
    @Autowired
    private ISalesOrderService salesOrderService;
    @Resource
    private ProductMapper productMapper;
    @Resource
    private SalesRuleSettingMapper salesRuleSettingMapper;
    @Autowired
    private IRepertoryFlowService iRepertoryFlowService;
    @Resource
    private PurchaseProductMapper purchaseProductMapper;
    @Resource
    private SalesPurchaseMapper salesPurchaseMapper;
    @Resource
    private PatientInfoMapper patientInfoMapper;
    @Autowired
    private IPurchaseService purchaseService;
    @Resource
    private SysDeptMapper sysDeptMapper;
    @Resource
    private MemberInfoMapper memberInfoMapper;
    @Autowired
    private IWalletRecordService walletRecordService;
    @Autowired
    private ISysTenantNotifyItemService sysTenantNotifyItemService;
    @Autowired
    private IPurchaseApplyService purchaseApplyService;
    @Autowired
    private ISysDeptService sysDeptService;
    /**
     * 查询销售单换货
     *
     * @param id 销售单换货主键
     * @return 销售单换货
     */
    @Override
    public SalesExchangeVo selectSalesExchangeById(Long id)
    {
        SalesExchangeVo salesExchangeVo = salesExchangeMapper.selectSalesExchangeById(id);
        SalesOrder salesOrder = salesOrderMapper.selectById(salesExchangeVo.getSalesOrderId());
        salesExchangeVo.setSalesNo(salesOrder.getSalesNo());
        salesExchangeVo.setCurrAge(salesOrder.getCurrentAge());
        PatientInfo patientInfo = patientInfoMapper.selectById(salesOrder.getPatientId());
        salesExchangeVo.setPatientPhone(patientInfo.getPhoneNumber());
        salesExchangeVo.setPatientName(patientInfo.getPatientName());
        salesExchangeVo.setSex(patientInfo.getSex());
        SysDept sysDept = sysDeptMapper.selectDeptById(salesOrder.getDeptId());
        salesExchangeVo.setSalesDeptName(sysDept.getDeptName());
        BigDecimal walletBalance = new BigDecimal("0.00");
        if(null != salesOrder.getPatientId()){
            MemberInfo memberInfo = memberInfoMapper.memberInfoByPatientId(salesOrder.getPatientId());
            if(null != memberInfo){
              walletBalance = walletBalance.add(memberInfo.getWalletBalance());
              salesExchangeVo.setMemberCardNo(memberInfo.getMemberCardNo());
            }
        }
        salesExchangeVo.setWalletBalance(walletBalance);


        List<SalesExchangeDetailParam> exchangeDetailList = exchangeDetailMapper.exchangeDetailList(id);
        salesExchangeVo.setExchangeDetailList(exchangeDetailList);

        return salesExchangeVo;
    }

    /**
     * 查询销售单换货列表
     *
     * @param salesExchange 销售单换货
     * @return 销售单换货
     */
    @Override
    public List<SalesExchange> selectSalesExchangeList(SalesExchange salesExchange)
    {
        return salesExchangeMapper.selectSalesExchangeList(salesExchange);
    }

    /**
     * 新增销售单换货
     *
     * @param salesExchangeParam 销售单换货
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult insertSalesExchange(SalesExchangeParam salesExchangeParam)
    {
        Long salesOrderId = salesExchangeParam.getSalesOrderId();
        SalesOrder salesOrder = salesOrderMapper.selectById(salesOrderId);
        salesExchangeParam.setExchangeNo(RedisCode.getCode("XSHH"));
        salesExchangeParam.setCreateBy(SecurityUtils.getLoginUser().getUserId());
        salesExchangeMapper.insertSalesExchange(salesExchangeParam);

        List<SalesExchangeDetailParam> exchangeDetailParamList = salesExchangeParam.getExchangeDetailParamList();

        // 判断是否要上传参数的类别
        SalesRuleSetting queryRule = new SalesRuleSetting();
        queryRule.setRuleSerialNo(2);
        SalesRuleSetting salesRuleSetting = salesRuleSettingMapper.queryMyRule(queryRule);
        List<String> ruleStringList= new ArrayList<>();
        ruleStringList.add("-99");
        if(Objects.nonNull(salesRuleSetting)){
            String ruleValue = salesRuleSetting.getRuleValue();
            JSONObject jsonObject = JSONObject.parseObject(ruleValue);
            String approvalDiscount = jsonObject.getString("uploadCategory");
            String[] split = approvalDiscount.split(",");
            ruleStringList= Stream.of(split).collect(Collectors.toList());

        }

        List<SalesOrderDetail> exchangeOrderDetailList = new ArrayList<>();
        // 优惠折扣
        BigDecimal discount = salesOrder.getDiscount();
        for (SalesExchangeDetailParam param:exchangeDetailParamList) {
            SalesExchangeDetail  exchangeDetail = new SalesExchangeDetail();
            BeanUtils.copyProperties(param,exchangeDetail);
            // 退货拆分
            Long salesOrderDetailId = param.getSalesOrderDetailId();
            SalesOrderDetail salesOrderDetail = orderDetailMapper.selectById(salesOrderDetailId);
            if(salesOrderDetail.getProductPurchaseType().equals(2)){
                DateTime parse = DateUtil.parse("2024-05-15 00:00:00", "yyyy-MM-dd HH:mm:ss");
                if(salesOrderDetail.getCreateTime().getTime() < parse.getTime()){
                    throw new ServiceException("商品名称："+salesOrderDetail.getProductName()+"的商品为无流水定制商品,不能进行换货操作！");
                }
            }

            exchangeDetail.setSalesSourceDetailStatus(salesOrderDetail.getProductStatus());
            SalesOrderDetail newOrderDetail = new SalesOrderDetail();
            BeanUtils.copyProperties(param,newOrderDetail);
            BigDecimal oldDetailSubtotal = new BigDecimal("0.00");
            if(!salesOrderDetail.getSellingNum().equals(param.getExchangeNum())){
                // 说明部分换货
                SalesOrderDetail oldOrderDetail = new SalesOrderDetail();
                // 拆分
                BeanUtils.copyProperties(salesOrderDetail,oldOrderDetail);
                Integer sellingNum = salesOrderDetail.getSellingNum();
                String useReceiveGift = salesOrderDetail.getUseReceiveGift();
                Integer exchangeNum = param.getExchangeNum();
                // 重新计算 优惠金额 和 小计
                BigDecimal discountAmount = salesOrderDetail.getDiscountAmount();
                BigDecimal subtotal = salesOrderDetail.getSubtotal();
                BigDecimal giftDeductionTotal = salesOrderDetail.getGiftDeductionTotal();
                BigDecimal reductionAmount = salesOrderDetail.getReductionAmount();
                BigDecimal sellingPrice = salesOrderDetail.getSellingPrice();

                if(StringUtils.isNotEmpty(useReceiveGift)){
                    // 使用了优惠卡
                    String[] split = useReceiveGift.split(",");
                    List<String> stringList= Stream.of(split).collect(Collectors.toList());
                    int length = split.length;
                    // 用了几张优惠卡
                    int num = sellingNum - exchangeNum ;
                    int cardUseNum = length - num; // 要退的卡数
                    List<String> returnGiftList = new ArrayList<>();
                    if(cardUseNum>0){
                        BigDecimal giftDeductionTotalDivide = giftDeductionTotal.divide(BigDecimal.valueOf(length), 4, BigDecimal.ROUND_HALF_UP);
                        BigDecimal returnGiftDeductionTotal = giftDeductionTotalDivide.multiply(BigDecimal.valueOf(cardUseNum));
                        oldOrderDetail.setGiftDeductionTotal(returnGiftDeductionTotal);
                        BigDecimal subtractGiftDeductionTotal = giftDeductionTotal.subtract(returnGiftDeductionTotal);
                        salesOrderDetail.setGiftDeductionTotal(subtractGiftDeductionTotal);
                        // 需要退会员卡了
                        for (int j = 0; j < cardUseNum; j++) {
                            returnGiftList.add(split[j]);
                        }
                        oldOrderDetail.setUseReceiveGift(StringUtils.join(returnGiftList,","));
                    }else {
                        oldOrderDetail.setUseReceiveGift(null);
                        oldOrderDetail.setGiftDeductionTotal(new BigDecimal(0.00));
                    }
                    // 更改原来商品明细的使用会员卡号
                    stringList.removeAll(returnGiftList);
                    salesOrderDetail.setUseReceiveGift(StringUtils.join(stringList,","));

                }
                BigDecimal returnReductionAmount =  reductionAmount.divide(BigDecimal.valueOf(sellingNum) ,2, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(exchangeNum));
                BigDecimal newSubtotal = new BigDecimal("0.00");
                if(discount != null && discount.doubleValue()>0){
                    newSubtotal = sellingPrice.multiply(BigDecimal.valueOf(exchangeNum)).subtract(oldOrderDetail.getGiftDeductionTotal()).multiply(discount).divide(new BigDecimal("10") ,4, BigDecimal.ROUND_HALF_UP).subtract(returnReductionAmount);// 因为先减了所以要加回去

                }else {
                    newSubtotal = sellingPrice.multiply(BigDecimal.valueOf(exchangeNum)).subtract(oldOrderDetail.getGiftDeductionTotal()).subtract(returnReductionAmount);

                }

                BigDecimal newDiscountAmount = sellingPrice.multiply(BigDecimal.valueOf(exchangeNum)).subtract(newSubtotal);
                oldOrderDetail.setSubtotal(newSubtotal);
                oldDetailSubtotal = oldDetailSubtotal.add(newSubtotal);
                oldOrderDetail.setReductionAmount(returnReductionAmount);
                oldOrderDetail.setDiscountAmount(newDiscountAmount);

                // 原来的也得重算
                BigDecimal subtract = discountAmount.subtract(newDiscountAmount);
                BigDecimal subtract1 = subtotal.subtract(newSubtotal);
                salesOrderDetail.setDiscountAmount(subtract);
                salesOrderDetail.setSubtotal(subtract1);
                // 原来抹零重新计算
                BigDecimal subtractReductionAmount = reductionAmount.subtract(returnReductionAmount);
                salesOrderDetail.setReductionAmount(subtractReductionAmount);

                oldOrderDetail.setSellingNum(exchangeNum);
                oldOrderDetail.setProductStatus(15);
                orderDetailMapper.insert(oldOrderDetail);
                exchangeDetail.setOldSalesOrderDetailId(oldOrderDetail.getId());
                int i1 = sellingNum - exchangeNum;
                salesOrderDetail.setSellingNum(i1);
                newOrderDetail.setGiftDeductionTotal(oldOrderDetail.getGiftDeductionTotal());
                newOrderDetail.setUseReceiveGift(oldOrderDetail.getUseReceiveGift());
                newOrderDetail.setAfterTreatmentNo(salesExchangeParam.getExchangeNo());
                newOrderDetail.setBeforeTreatmentNo(oldOrderDetail.getAfterTreatmentNo());
            }else {
                salesOrderDetail.setProductStatus(15);
                exchangeDetail.setOldSalesOrderDetailId(salesOrderDetail.getId());
                newOrderDetail.setGiftDeductionTotal(salesOrderDetail.getGiftDeductionTotal());
                newOrderDetail.setUseReceiveGift(salesOrderDetail.getUseReceiveGift());
                newOrderDetail.setAfterTreatmentNo(salesExchangeParam.getExchangeNo());
                newOrderDetail.setBeforeTreatmentNo(salesOrderDetail.getAfterTreatmentNo());
                exchangeDetail.setOldSalesOrderDetailId(salesOrderDetail.getId());
            }

            orderDetailMapper.updateById(salesOrderDetail);
            exchangeDetail.setSalesOrderId(salesOrderId);
            exchangeDetail.setSalesSourceDetailId(salesOrderDetail.getId());
            // 再把换货商品插入到销售明细里面
            // 判断状态
            newOrderDetail.setProductStatus(11);
            newOrderDetail.setDetailType(1);
            newOrderDetail.setDeptId(salesOrderDetail.getDeptId());
            newOrderDetail.setSalesId(salesOrderId);
            newOrderDetail.setSellingNum(param.getExchangeNum());
            newOrderDetail.setRemark(param.getRemark());
            //  判断需要上传附件  然后设置 isUploadFile值
            Product product = productMapper.selectById(param.getProductId());
            if(Objects.nonNull(product.getCategoryId())){
                if(ruleStringList.contains(product.getCategoryId().toString()) && param.getProductPurchaseType().equals(2)){
                    newOrderDetail.setProductStatus(3);
                    newOrderDetail.setIsUploadFile(1);
                }
            }
            newOrderDetail.setSubtotal(oldDetailSubtotal.add(param.getDifferenceAmount()));
            orderDetailMapper.insert(newOrderDetail);
            exchangeOrderDetailList.add(newOrderDetail);
            exchangeDetail.setNewSalesOrderDetailId(newOrderDetail.getId());
            exchangeDetail.setSalesExchangeId(salesExchangeParam.getId());
            exchangeDetail.setDetailReturnWarehouseId(param.getDetailReturnWarehouseId());

            exchangeDetailMapper.insert(exchangeDetail);

        }
        // 插入 费用账单管理
        ExpenseBill expenseBill = new ExpenseBill();
        expenseBill.setDeptId(salesOrder.getDeptId());
        expenseBill.setTenantId(salesOrder.getTenantId());
        expenseBill.setPatientId(salesOrder.getPatientId());
        expenseBill.setActCost(salesOrder.getCollectionAmount());
        expenseBill.setBizNo(salesExchangeParam.getExchangeNo());
        expenseBill.setBizType(2);
        expenseBill.setBizId(salesExchangeParam.getId());
        expenseBill.setReceivableCost(salesOrder.getProductTotalAmount());
        expenseBill.setPreferentialCost(salesOrder.getPreferentialAmount());
        expenseBill.setCreateBy(SecurityUtils.getLoginUser().getUserId());
        expenseBillMapper.insertExpenseBill(expenseBill);
        // 预占库存
        List<SalesOrderDetail> salesOrderDetails = orderDetailMapper.selectBySalesId(salesExchangeParam.getSalesOrderId());
//        List<SalesOrderDetail> exchangeDetailList = salesOrderDetails.stream().filter(o -> o.getDetailType() == 1).collect(Collectors.toList());
        boolean b = occupyPurchaseProduct(salesOrder, exchangeOrderDetailList, 1);
        if(false == b){
            throw new ServiceException("新增失败！原因：增加销售单库存流水失败。");
        }
        // 遍历更新销售单状态
        Integer newOrderStatus = ProcessOrderUtil.processOrderStatusByDetails(salesOrderDetails);
        salesOrderMapper.updateOrderStatus(salesExchangeParam.getSalesOrderId(),newOrderStatus);
        return AjaxResult.success(salesExchangeParam.getId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult cancelSalesExchange(SalesExchangeParam exchangeParam){
        SalesExchangeDetail salesSalesDetail = new SalesExchangeDetail();
        salesSalesDetail.setSalesExchangeId(exchangeParam.getId());
        SalesExchange salesExchange = salesExchangeMapper.selectById(exchangeParam.getId());
        salesExchange.setExchangeStatus(3);
        salesExchangeMapper.updateById(salesExchange);
        List<SalesExchangeDetail> salesExchangeDetails = exchangeDetailMapper.selectSalesExchangeDetailList(salesSalesDetail);
        // 取消之后就得恢复成之前的了
        for (SalesExchangeDetail detail:salesExchangeDetails) {
            Long sourceSalesDetailId = detail.getSalesSourceDetailId();
            Long oldSalesOrderDetailId = detail.getOldSalesOrderDetailId();
            SalesOrderDetail sourceSalesOrderDetail = orderDetailMapper.selectById(sourceSalesDetailId);
            if(!sourceSalesDetailId.equals(oldSalesOrderDetailId)){
                SalesOrderDetail oldSalesOrderDetail = orderDetailMapper.selectById(oldSalesOrderDetailId);
                sourceSalesOrderDetail.setSubtotal(sourceSalesOrderDetail.getSubtotal().add(oldSalesOrderDetail.getSubtotal()));
                sourceSalesOrderDetail.setGiftDeductionTotal(sourceSalesOrderDetail.getGiftDeductionTotal().add(oldSalesOrderDetail.getGiftDeductionTotal()));
                sourceSalesOrderDetail.setDiscountAmount(sourceSalesOrderDetail.getDiscountAmount().add(oldSalesOrderDetail.getDiscountAmount()));
                sourceSalesOrderDetail.setReductionAmount(sourceSalesOrderDetail.getReductionAmount().add(oldSalesOrderDetail.getReductionAmount()));
                // 原来的恢复
                String useReceiveGift = oldSalesOrderDetail.getUseReceiveGift();
                List<String> strs = new ArrayList<>();
                if(StringUtils.isNotEmpty(useReceiveGift)){
                    String[] split = useReceiveGift.split(",");
                    List<String> stringList= Stream.of(split).collect(Collectors.toList());
                    strs.addAll(stringList);
                }
                if(StringUtils.isNotEmpty(sourceSalesOrderDetail.getUseReceiveGift())){
                    String[] split = sourceSalesOrderDetail.getUseReceiveGift().split(",");
                    List<String> stringList= Stream.of(split).collect(Collectors.toList());
                    strs.addAll(stringList);
                }
                sourceSalesOrderDetail.setUseReceiveGift(StringUtils.join(strs,","));
                sourceSalesOrderDetail.setSellingNum(sourceSalesOrderDetail.getSellingNum()+oldSalesOrderDetail.getSellingNum());
                sourceSalesOrderDetail.setProductStatus(detail.getSalesSourceDetailStatus());
                orderDetailMapper.updateById(sourceSalesOrderDetail);
                // 拆开的删除
                oldSalesOrderDetail.setProductStatus(20);
                orderDetailMapper.updateById(oldSalesOrderDetail);
//                orderDetailMapper.deleteById(oldSalesOrderDetail.getId());
            }else {
                sourceSalesOrderDetail.setProductStatus(detail.getSalesSourceDetailStatus());
                orderDetailMapper.updateById(sourceSalesOrderDetail);
            }
            // 把新增换货的删掉
            SalesOrderDetail newSalesOrderDetail = orderDetailMapper.selectById(detail.getNewSalesOrderDetailId());
            newSalesOrderDetail.setProductStatus(20);
            orderDetailMapper.updateById(newSalesOrderDetail);
        }
        // 删除生成的费用账单
        ExpenseBill expenseBill = new ExpenseBill();
        expenseBill.setBizId(salesExchange.getId());
        expenseBill.setBizType(2);
        expenseBillMapper.deleteByParam(expenseBill);
        salesExchangeMapper.updateById(salesExchange);
        // 遍历更新销售单状态
        SalesOrder salesOrder = salesOrderMapper.selectById(salesExchange.getSalesOrderId());
        List<SalesOrderDetail> salesOrderDetails = orderDetailMapper.selectBySalesId(salesExchange.getSalesOrderId());
        List<SalesOrderDetail> exchangeDetailList = salesOrderDetails.stream().filter(o -> o.getDetailType() == 1).collect(Collectors.toList());
        boolean b = occupyPurchaseProduct(salesOrder, exchangeDetailList, 2);
        if(false == b){
            throw new ServiceException("新增失败！原因：取消销售单换货库存流水失败。");
        }
        Integer newOrderStatus = ProcessOrderUtil.processOrderStatusByDetails(salesOrderDetails);
        salesOrderMapper.updateOrderStatus(salesExchange.getSalesOrderId(),newOrderStatus);
        return AjaxResult.success("操作成功！");
    }


    @Override
    public AjaxResult confirmSalesExchange(SalesExchangeParam exchangeParam){
        // 确认换货里面操作
        SalesExchange salesExchange = salesExchangeMapper.selectById(exchangeParam.getId());
        salesExchange.setExchangeStatus(2);

        SalesOrder salesOrder = salesOrderMapper.selectById(salesExchange.getSalesOrderId());

        // 1. 钱包支付处理
        if((Objects.nonNull(exchangeParam.getWalletPay()) && exchangeParam.getWalletPay().doubleValue()>0) ){
            MemberInfo memberInfo = memberInfoMapper.memberInfoByPatientId(salesOrder.getPatientId());
            BigDecimal walletBalance = memberInfo.getWalletBalance();
            if(Objects.nonNull(exchangeParam.getWalletPay()) && walletBalance.doubleValue()<exchangeParam.getWalletPay().doubleValue()){
                return AjaxResult.error("钱包余额不足！");
            }else {
                if(Objects.nonNull(exchangeParam.getWalletPay()) && exchangeParam.getWalletPay().doubleValue()>0){
                    walletBalance = walletBalance.subtract(exchangeParam.getWalletPay());
                    memberInfo.setWalletBalance(walletBalance);
                    // 新增消费流水新增
                    int i = walletRecordService.addBizRecord(salesOrder.getMemberCardNo(), 4, 2, salesOrder.getSalesNo(), exchangeParam.getWalletPay(), salesOrder.getDeptId());
                    if(i<=0){
                        throw new ServiceException("销售单换货确认付款失败！原因：钱包销售扣款新增流水失败。");
                    }
                }
            }
            memberInfoMapper.updateById(memberInfo);
            // 发送账户变动短信
            MemberMsgInfo msgInfo = new MemberMsgInfo();
            msgInfo.setId(memberInfo.getId());
            BeanUtils.copyProperties(memberInfo,msgInfo);
            // 以订单的门店为准
            msgInfo.setDeptId(salesOrder.getDeptId());
            msgInfo.setVariableIntegral(new BigDecimal("0"));
            msgInfo.setVariableAmount(exchangeParam.getWalletPay());
            sysTenantNotifyItemService.sendMemberInfoMsg(msgInfo,1, SecurityUtils.getLoginUser().getUser());
        }
        // 2. 换货单主表处理
        Date date = new Date();
        salesExchange.setPaymentType(exchangeParam.getPaymentType());
        salesExchange.setPaymentTime(date);
        salesExchange.setWalletPay(exchangeParam.getWalletPay());
        salesExchange.setPendingAmount(exchangeParam.getPendingAmount());
        salesExchangeMapper.updateById(salesExchange);
        // 3. 刷新患者数据中的“累计消费”
        PatientInfo patientInfo = patientInfoMapper.selectById(salesOrder.getPatientId());
        BigDecimal accumulatedConsumption = patientInfo.getAccumulatedConsumption().add(salesOrder.getCollectionAmount());// 计算累计消费的金额
        patientInfo.setAccumulatedConsumption(accumulatedConsumption);
        patientInfoMapper.updateById(patientInfo);

        // 构建会员名称，待后续使用
        String memberName = ProcessOrderUtil.processMemberName(patientInfo);
        // 获取换货单详情数据
        SalesExchangeDetail salesExchangeDetail = new SalesExchangeDetail();
        salesExchangeDetail.setSalesExchangeId(exchangeParam.getId());
        List<SalesExchangeDetail> salesExchangeDetails = exchangeDetailMapper.selectSalesExchangeDetailList(salesExchangeDetail);
        for (SalesExchangeDetail detail : salesExchangeDetails) {
            // 根据换货单详情数据，去检索换入，换出的订单详情
            SalesOrderDetail oldDetail = orderDetailMapper.selectById(detail.getOldSalesOrderDetailId());
            SalesOrderDetail newDetail = orderDetailMapper.selectById(detail.getNewSalesOrderDetailId());
            // 更新换出的商品
            // 因为存在连续换货的情况，连续换货会存在多次补差价。这些差价要叠加计算，才是此“链”上的商品实际卖去的钱
            BigDecimal actualSubtotal = oldDetail.getActualSubtotal().add(newDetail.getSubtotal());  // 这里只要检索出换货前的实际小计，然后与此次小计（差价）相加即可。
            newDetail.setActualSubtotal(actualSubtotal);
            newDetail.setProductStatus(11);// 待交付
            orderDetailMapper.updateById(newDetail);
            // 更新换入的商品
            oldDetail.setActualSubtotal(new BigDecimal(0));// 换入的商品实际卖出去的钱为0，因为该金额已传递到换出商品的实际金额中。
            oldDetail.setProductStatus(18);// 已换货
            orderDetailMapper.updateById(oldDetail);
            // 获取换货单详情的销售出库日志
            RepertoryFlow repertoryFlowParam = new RepertoryFlow();
            repertoryFlowParam.setStorageType(10);
            repertoryFlowParam.setBusinessId(detail.getSalesSourceDetailId());
            List<PurchaseProduct> repertoryFlows = iRepertoryFlowService.selectListByRepertoryFlow(repertoryFlowParam);
            // 查出原销售的订单
            SalesOrderDetail sourceSalesOrderDetail = orderDetailMapper.selectById(detail.getSalesSourceDetailId());
            // 当这两个字段一样时，说明没有拆单，是全部换货
            if(detail.getSalesSourceDetailId().equals(detail.getOldSalesOrderDetailId())){
                // 判断全部换货的退货仓库是否与原仓库一致
                if(!sourceSalesOrderDetail.getWarehouseId().equals(detail.getDetailReturnWarehouseId())) {
                    // 如果不一致，则说明是换到其他仓库里面，所以这里要加一笔新的采购单数据。
                    // 声明采购单，然后赋值详情的字段
                    PurchaseProduct purchaseProduct = new PurchaseProduct();
                    PurchaseProduct product = repertoryFlows.get(0);
                    BeanUtils.copyProperties(product,purchaseProduct);
                    /*
                    product.setWarehouseId(oldDetail.getWarehouseId());
                    product.setWarehouseName(oldDetail.getWarehouseName());*/
                    product.setWarehouseId(detail.getDetailReturnWarehouseId());
                    product.setWarehouseName(detail.getDetailReturnWarehouseName());
                    purchaseProduct.setMemberId(patientInfo.getId());
                    purchaseProduct.setMemberName(memberName);
                    purchaseProduct.setPrice(oldDetail.getSellingPrice());
                    purchaseProduct.setAvailableStock(oldDetail.getSellingNum());
                    purchaseProduct.setStorageNum(oldDetail.getSellingNum());
                    purchaseProduct.setInventoryQuantity(oldDetail.getSellingNum());
                    purchaseProduct.setSubtotal(oldDetail.getSubtotal());
                    purchaseProduct.setCreateTime(new Date());
                    // 声明采购单详情，然后赋值详情的字段
                    List<PurchaseProduct> purchaseProductList = Arrays.asList(purchaseProduct);
                    Purchase purchase = new Purchase();
                    purchase.setStorageType(14);
                    purchase.setPurchaseNumber(salesOrder.getSalesNo());
                    purchase.setSupplierId(purchaseProduct.getSupplierId());
                    purchase.setSupplierName(purchaseProduct.getSupplierName());
                    purchase.setWarehouseId(product.getWarehouseId());
                    purchase.setWarehouseName(product.getWarehouseName());
                    purchase.setStatus(2);
                    purchase.setPurchaseProductList(purchaseProductList);
                    // 调用通用的采购单新增方法，把新的采购单数据给加进去。
                    purchaseService.insertPurchase(purchase);
                }else {
                    //  如果一致，则说明要把原来的给加回去
                    for (PurchaseProduct purchaseProduct : repertoryFlows) {
                        // 更新后用库存 = 剩余库存 + 此次退货的库存
                        int availableStock = purchaseProduct.getAvailableStock() + newDetail.getSellingNum();
                        purchaseProduct.setAvailableStock(availableStock);
                        purchaseProduct.setPrice(sourceSalesOrderDetail.getSellingPrice());
                        purchaseProduct.setMemberId(patientInfo.getId());
                        purchaseProduct.setMemberName(memberName.toString());
                        purchaseProductMapper.updateById(purchaseProduct);
                    }
                    // 新增流水记录
                    if(!CollectionUtils.isEmpty(repertoryFlows)){
                        //new一个当前时间放入流水记录中覆盖它，避免换货的出/入库流水记录的创建时间用的是“销售出/入库”时的创建时间。
                        repertoryFlows.forEach(data -> {
                            data.setCreateTime(new Date());
                            data.setRemark(null);  // 备注设为null，也是避免用的是“销售出/入库”的数据
                            data.setWarehouseName(detail.getDetailReturnWarehouseName()); // 换货单的退货流水对应的仓库应该设为退货的仓库名称
                        });
                        boolean repertoryFlow = iRepertoryFlowService.saveRepertoryFlow(repertoryFlows, 1, 14);
                        if (!repertoryFlow) {
                            throw new ServiceException("销售单退货失败！原因：销售单退货库存流水失败。");
                        }
                    }
                }
            }else {

                // 判断换货的退货仓库是否与原仓库一致
                if (sourceSalesOrderDetail.getWarehouseId().equals(detail.getDetailReturnWarehouseId())) {
                    // 如果退货仓库和原来仓库一致，则退货到原来的库存中
                    List<PurchaseProduct> newRepertoryFlows = new ArrayList<>();
                    // 此次换货（剩余）数量
                    Integer exchangeNum = detail.getExchangeNum();
                    for (PurchaseProduct purchaseProduct : repertoryFlows) {

                        purchaseProduct.setMemberId(patientInfo.getId());
                        purchaseProduct.setMemberName(memberName);
                        // 开始根据销售出库的流水中的记录，去回退商品库存
                        Integer beforeStock = purchaseProduct.getAvailableStock(); // 当前剩余库存数量
                        final Integer saleStock = purchaseProduct.getInventoryQuantity(); // 流水记录的销售出库的数量
                        exchangeNum = exchangeNum - saleStock;  // 下一轮换货（剩余）数量 = 上一轮换货（剩余）数量 - 流水记录的销售出库的数量

                        if (exchangeNum > 0) {
                            // 新的剩余库存数量 = 当前剩余库存数量 + 流水记录的销售出库的数量
                            purchaseProduct.setAvailableStock(beforeStock + saleStock);
                            purchaseProductMapper.updateById(purchaseProduct); // 更新采购单中的可用库存
                            newRepertoryFlows.add(purchaseProduct); // 添加日志
                        } else {
                            // exchangeNum 出现负数，说明是换的数量大于原来的订单销售出去的数量
                            // 能力有限，看不懂这里为什么要+exchangeNum
                            purchaseProduct.setAvailableStock(beforeStock + saleStock + exchangeNum);
                            purchaseProductMapper.updateById(purchaseProduct); // 更新采购单中的可用库存
                            // 构造流水的日志
                            int i = saleStock + exchangeNum;
                            BigDecimal oldSubtotal = purchaseProduct.getSubtotal();
                            BigDecimal dividePrice = oldSubtotal.divide(BigDecimal.valueOf(saleStock), 4,BigDecimal.ROUND_HALF_UP);
                            BigDecimal multiply = dividePrice.multiply(BigDecimal.valueOf(i));
                            purchaseProduct.setSubtotal(multiply);
                            purchaseProduct.setInventoryQuantity(i);
                            purchaseProduct.setPrice(sourceSalesOrderDetail.getSellingPrice());
                            newRepertoryFlows.add(purchaseProduct); // 添加日志
                            break;
                        }
                    }
                    // 新增流水记录
                    if (!CollectionUtils.isEmpty(newRepertoryFlows)) {
                        //new一个时间放入流水记录中覆盖它，避免换货的出/入库流水记录的创建时间用的是“销售出/入库”时的创建时间
                        newRepertoryFlows.forEach(data -> {
                            data.setCreateTime(new Date());
                            // 备注设为null，也是避免用的是“销售出/入库”的数据
                            data.setRemark(null);
                            // 换货单的退货流水对应的仓库应该设为退货的仓库名称
                            data.setWarehouseName(detail.getDetailReturnWarehouseName());
                        });
                        boolean repertoryFlow = iRepertoryFlowService.saveRepertoryFlow(newRepertoryFlows, 1, 14);
                        if (!repertoryFlow) {
                            throw new ServiceException("销售单换货失败！原因：销售单换货退回仓库库存流水失败。");
                        }
                    }
                } else {
                    // 如果退货仓库和原来仓库不一致，则创建新的入库单，入库到指定的仓库
                    PurchaseProduct repertoryFlow = repertoryFlows.get(0);
                    repertoryFlow.setWarehouseId(detail.getDetailReturnWarehouseId());
                    repertoryFlow.setWarehouseName(detail.getDetailReturnWarehouseName());
                    // 生成入库单,商品数据
                    PurchaseProduct purchaseProduct = new PurchaseProduct();
                    BeanUtils.copyProperties(repertoryFlow, purchaseProduct);
                    purchaseProduct.setMemberId(patientInfo.getId());
                    purchaseProduct.setMemberName(memberName);
                    purchaseProduct.setPrice(oldDetail.getSellingPrice());
                    purchaseProduct.setAvailableStock(oldDetail.getSellingNum());
                    purchaseProduct.setStorageNum(oldDetail.getSellingNum());
                    purchaseProduct.setInventoryQuantity(oldDetail.getSellingNum());
                    purchaseProduct.setSubtotal(oldDetail.getSubtotal());

                    purchaseProduct.setCreateTime(new Date());
                    List<PurchaseProduct> purchaseProductList = Arrays.asList(purchaseProduct);
                    // 生成入库单数据
                    Purchase purchase = new Purchase();
                    purchase.setStorageType(14);//换货退货入库
                    purchase.setPurchaseNumber(salesOrder.getSalesNo());
                    purchase.setSupplierId(purchaseProduct.getSupplierId());
                    purchase.setSupplierName(purchaseProduct.getSupplierName());
                    purchase.setWarehouseId(purchaseProduct.getWarehouseId());
                    purchase.setWarehouseName(purchaseProduct.getWarehouseName());
                    purchase.setStatus(2);
                    purchase.setPurchaseProductList(purchaseProductList);
                    purchaseService.insertPurchase(purchase);
                }
            }
        }
        //换定制采购商品时的额外处理，需要生成定制采购申请
        insertPurchaseApplyForExchange(salesExchange, salesOrder, salesExchangeDetails);
        // 更新费用账单
        ExpenseBill expenseBill = new ExpenseBill();
        expenseBill.setBizId(exchangeParam.getId());
        expenseBill.setBizType(2);
        expenseBill.setStatus(1);
        expenseBillMapper.updateByParam(expenseBill);
        // 通过换货单id，换取原订单的详情数据。再通过计算这些详情数据的状态，得出原订单最新状态后，再更新原订单（状态）。
        List<SalesOrderDetail> salesOrderDetails = exchangeDetailMapper.selectBySalesExchangeId(exchangeParam.getId());
        Integer newOrderStatus = ProcessOrderUtil.processOrderStatusByDetails(salesOrderDetails);
        salesOrderMapper.updateOrderStatus(exchangeParam.getSalesOrderId(),newOrderStatus);
        // 返回
        return AjaxResult.success("操作成功！");
    }

    /**
     * 生成定制采购申请（为了换货）
     * @param salesExchange
     * @param salesOrder
     * @param salesExchangeDetails
     */
    private void insertPurchaseApplyForExchange(SalesExchange salesExchange, SalesOrder salesOrder,
                                          List<SalesExchangeDetail> salesExchangeDetails) {

        List<SalesOrderDetail> purchaseApplyList = new ArrayList<>();
        // 判断换货的商品是不是定制采购 如果定制采购 则需要生成定制采购申请
        for (SalesExchangeDetail detail : salesExchangeDetails) {
            SalesOrderDetail salesOrderDetail = orderDetailMapper.selectById(detail.getNewSalesOrderDetailId());
            // 判断是否是定制采购
            if (salesOrderDetail.getProductPurchaseType().equals(2)) {
                salesOrderDetail.setProductStatus(4);// 默认productStatus = 4
                if (salesOrderDetail.getIsUploadFile().equals(1)) {
                    salesOrderDetail.setProductStatus(3); // 如果需要上传参数附件，则productStatus = 3
                }
                orderDetailMapper.updateById(salesOrderDetail);
                salesOrderDetail.setRemark(salesExchange.getExchangeNo() + "换货商品定制采购");
                purchaseApplyList.add(salesOrderDetail);// 讲订单详情放入needPurchaseDetailList中
            }
        }
        // 从needPurchaseDetailList中取出订单详情，新增定制采购申请单数据
        if (!CollectionUtils.isEmpty(purchaseApplyList)) {
            List<SalesOrderDetail> collect = purchaseApplyList.stream()
                    .filter(o -> o.getProductStatus().equals(4)).collect(Collectors.toList());
            // 不知道前人为什么要加上这个。结合前面的代码，只要有一笔productStatus=3，那么就不生成定制采购申请？
            if (collect.size() == purchaseApplyList.size()) {
                SalesPurchaseApplyVo salesPurchaseApplyVo = new SalesPurchaseApplyVo();
                salesPurchaseApplyVo.setSalesNo(salesOrder.getSalesNo());
                salesPurchaseApplyVo.setSalesDeptId(salesOrder.getDeptId());
                salesPurchaseApplyVo.setSalesOrderId(salesOrder.getId());
                salesPurchaseApplyVo.setOrderDetailList(purchaseApplyList);
                purchaseApplyService.addSalesPurchaseApply(salesPurchaseApplyVo);
            }
        }
    }




    private boolean occupyPurchaseProduct(SalesOrder salesOrder,List<SalesOrderDetail> salesOrderDetails,Integer editType){

        for (SalesOrderDetail salesDetail:salesOrderDetails) {
            if(salesDetail.getProductPurchaseType().equals(2)){
                continue;
            }
            if(editType.equals(1)){
                PurchaseProduct queryProductParam = new PurchaseProduct();
                BeanUtils.copyProperties(salesDetail,queryProductParam);
                List<PurchaseProduct> purchaseProductList = purchaseProductMapper.getSalesListByParam(queryProductParam);
                if(CollectionUtils.isEmpty(purchaseProductList)){
                    throw new ServiceException("销售单提交失败！原因：商品名称:"+queryProductParam.getProductName()+",参数:"+queryProductParam.getProductParam()+"库存为0，请重新选择商品！");
                }
                List<PurchaseProduct> purchaseProducts = iRepertoryFlowService.convertFlowData(purchaseProductList, salesDetail.getSellingNum(), salesOrder.getSalesNo(),salesDetail.getId());
                // setInventoryQuantity
                for (PurchaseProduct purchaseProduct:purchaseProducts) {
                    SalesPurchase salesPurchase = new SalesPurchase();
                    salesPurchase.setSalesId(salesOrder.getId());
                    salesPurchase.setDetailId(salesDetail.getId());
                    salesPurchase.setPurchaseProductId(purchaseProduct.getId());
                    salesPurchase.setPurchaseProductNum(purchaseProduct.getInventoryQuantity());
                    salesPurchaseMapper.insert(salesPurchase);
                }
            }else{
                SalesPurchase salesPurchase = new SalesPurchase();
                salesPurchase.setSalesId(salesOrder.getId());
                salesPurchase.setDetailId(salesDetail.getId());
                List<PurchaseProduct> purchaseProductList = salesPurchaseMapper.selectPurchaseList(salesPurchase);
                for (PurchaseProduct purchaseProduct:purchaseProductList) {
                    Integer inventoryQuantity = purchaseProduct.getInventoryQuantity();
                    Integer availableStock = purchaseProduct.getAvailableStock();
                    purchaseProduct.setAvailableStock(availableStock+inventoryQuantity);
                    purchaseProductMapper.updateById(purchaseProduct);
                }
            }
        }

        return true;

    }

    /**
     * 修改销售单换货
     *
     * @param salesExchange 销售单换货
     * @return 结果
     */
    @Override
    public int updateSalesExchange(SalesExchange salesExchange)
    {
        salesExchange.setUpdateTime(DateUtils.getNowDate());
        return salesExchangeMapper.updateSalesExchange(salesExchange);
    }

    /**
     * 批量删除销售单换货
     *
     * @param ids 需要删除的销售单换货主键
     * @return 结果
     */
    @Override
    public int deleteSalesExchangeByIds(Long[] ids)
    {
        return salesExchangeMapper.deleteSalesExchangeByIds(ids);
    }

    /**
     * 删除销售单换货信息
     *
     * @param id 销售单换货主键
     * @return 结果
     */
    @Override
    public int deleteSalesExchangeById(Long id)
    {
        return salesExchangeMapper.deleteSalesExchangeById(id);
    }
}
